import hashlib
from django.contrib.auth.models import AbstractUser
from django.db import models

from utils import dispatch
from utils.models import CoreModel, SoftDeleteModel, DeptBelongModel


class Dept(CoreModel, SoftDeleteModel):
    parent = models.ForeignKey(
        to='Dept',
        on_delete=models.DO_NOTHING,
        verbose_name='上级区域',
        null=True,
        db_constraint=False
    )
    name = models.CharField(max_length=100, verbose_name='名称')
    level = models.CharField(max_length=1, verbose_name='1市')
    sort = models.IntegerField(default=100, verbose_name='顺序', help_text='顺序')

    class Meta:
        managed = False
        db_table = 'system_dept'
        verbose_name = '地区表'
        verbose_name_plural = verbose_name
        ordering = ('sort', 'id')


class Users(CoreModel, AbstractUser, DeptBelongModel):
    username = models.CharField(max_length=150, unique=True, db_index=True, verbose_name='账号', help_text='账号')
    email = models.EmailField(max_length=255, verbose_name='邮箱', null=True, blank=True, help_text='邮箱')
    mobile = models.CharField(max_length=20, verbose_name='电话', null=True, blank=True, help_text='电话')
    avatar = models.CharField(max_length=255, verbose_name='头像', null=True, blank=True, help_text='头像')
    name = models.CharField(max_length=40, verbose_name='用户名', help_text='用户名')
    role = models.ManyToManyField(to='Role', blank=True, verbose_name='所属部门', db_constraint=False, help_text='关联角色')
    status = models.BooleanField(default=True, verbose_name='用户状态', null=True, blank=True, help_text='用户状态')
    type = models.CharField(max_length=2, verbose_name='用户类型', help_text='1web')
    dept_id = models.IntegerField(null=True, verbose_name='部门id')
    groups = None
    user_permissions = None

    #    def set_password(self, raw_password):
    #        super().set_password(hashlib.md5(raw_password.encode(encoding='UTF-8')).hexdigest())

    def delete(self, using=None, soft_delete=True, *args, **kwargs):
        """重写删除方法,直接开启软删除"""
        self.is_active = False
        self.save(using=using)

    class Meta:
        managed = False
        db_table = 'system_users'
        verbose_name = '用户表'
        verbose_name_plural = verbose_name
        ordering = ('-create_time',)


class Role(CoreModel):
    name = models.CharField(max_length=64, verbose_name='名称', help_text='名称')
    sort = models.IntegerField(default=1, verbose_name='顺序', help_text='顺序')
    DATASCOPE_CHOICES = (
        (0, '仅本人数据权限'),
        (1, '本部门及以下数据权限'),
        (2, '自定义数据权限'),
        (3, '全部数据权限'),
        (4, '本部门数据权限'),
    )
    data_range = models.IntegerField(default=0, choices=DATASCOPE_CHOICES, verbose_name='数据权限范围')
    menu = models.ManyToManyField(to='Menu', verbose_name='关联菜单', db_constraint=False, help_text='关联菜单')
    permission = models.ManyToManyField(to='MenuButton', verbose_name='关联菜单的接口按钮', db_constraint=False)
    dept = models.ManyToManyField(to="Dept", verbose_name="数据权限-关联部门", db_constraint=False,
                                  help_text="数据权限-关联部门")

    class Meta:
        managed = False
        db_table = 'system_role'
        verbose_name = '角色表'
        verbose_name_plural = verbose_name
        ordering = ('sort', 'id')


class Menu(CoreModel):
    parent = models.ForeignKey(
        to='Menu',
        on_delete=models.CASCADE,
        verbose_name='上级菜单',
        null=True,
        blank=True,
        db_constraint=False,
        help_text='上级菜单',
    )
    icon = models.CharField(max_length=64, verbose_name='菜单图标', null=True, blank=True, help_text='菜单图标')
    name = models.CharField(max_length=64, verbose_name='菜单名称', help_text='菜单名称')
    sort = models.IntegerField(default=1, verbose_name='显示排序', null=True, blank=True, help_text='显示排序')
    is_link = models.BooleanField(default=False, verbose_name='是否外链', help_text='是否外链')
    is_catalog = models.BooleanField(default=False, verbose_name='是否目录', help_text='是否目录')
    web_path = models.CharField(max_length=128, verbose_name='路由地址', null=True, blank=True, help_text='路由地址')
    component = models.CharField(max_length=128, verbose_name='组件地址', null=True, blank=True, help_text='组件地址')
    component_name = models.CharField(max_length=50, verbose_name='组件名称', null=True, blank=True, help_text='组件名称')
    status = models.BooleanField(default=True, blank=True, verbose_name='菜单状态', help_text='菜单状态')
    cache = models.BooleanField(default=False, blank=True, verbose_name='是否页面缓存', help_text='是否页面缓存')
    visible = models.BooleanField(default=True, blank=True, verbose_name='侧边栏中是否显示', help_text='侧边栏中是否显示')

    class Meta:
        managed = False
        db_table = 'system_menu'
        verbose_name = '菜单表'
        verbose_name_plural = verbose_name
        ordering = ('sort', 'id')


class MenuButton(CoreModel):
    menu = models.ForeignKey(
        to='Menu',
        db_constraint=False,
        related_name='menu_permission',
        on_delete=models.CASCADE,
        verbose_name='关联菜单',
        help_text='关联菜单',
    )
    name = models.CharField(max_length=64, verbose_name='名称', help_text='名称')
    value = models.CharField(max_length=64, verbose_name='权限值', help_text='权限值')
    api = models.CharField(max_length=200, verbose_name='接口地址', help_text='接口地址')
    METHOD_CHOICES = (
        (0, 'GET'),
        (1, 'POST'),
        (2, 'PUT'),
        (3, 'DELETE'),
    )
    method = models.IntegerField(default=0, verbose_name='接口请求方法', null=True, blank=True, help_text='接口请求方法')

    class Meta:
        managed = False
        db_table = 'system_menu_button'
        verbose_name = '菜单权限表'
        verbose_name_plural = verbose_name
        ordering = ('-name', 'id')


class Dictionary(CoreModel, SoftDeleteModel):
    TYPE_LIST = (
        (0, 'text'),
        (1, 'number'),
        (2, 'date'),
        (3, 'datetime'),
        (4, 'time'),
        (5, 'files'),
        (6, 'boolean'),
        (7, 'images'),
    )
    label = models.CharField(max_length=100, blank=True, null=True, verbose_name='字典名称', help_text='字典名称')
    value = models.CharField(max_length=200, blank=True, null=True, verbose_name='字典编号', help_text='字典编号/实际值')
    parent = models.ForeignKey(
        to='self',
        related_name='sublist',
        db_constraint=False,
        on_delete=models.PROTECT,
        blank=True,
        null=True,
        verbose_name='父级',
        help_text='父级',
    )
    type = models.IntegerField(choices=TYPE_LIST, default=0, verbose_name='数据值类型', help_text='数据值类型')
    color = models.CharField(max_length=20, blank=True, null=True, verbose_name='颜色', help_text='颜色')
    is_value = models.BooleanField(default=False, verbose_name='是否为value值', help_text='是否为value值,用来做具体值存放')
    status = models.BooleanField(default=True, verbose_name='状态', help_text='状态')
    sort = models.IntegerField(default=1, verbose_name='显示排序', null=True, blank=True, help_text='显示排序')
    remark = models.CharField(max_length=1000, blank=True, null=True, verbose_name='备注', help_text='备注')

    class Meta:
        managed = False
        db_table = 'system_dictionary'
        verbose_name = '字典表'
        verbose_name_plural = verbose_name
        ordering = ('sort', '-create_time')

    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
        super().save(force_insert, force_update, using, update_fields)
        dispatch.refresh_dictionary()  # 有更新则刷新字典配置

    def delete(self, using=None, keep_parents=False):
        res = super().delete(using, keep_parents)
        dispatch.refresh_dictionary()
        return res


class OperationLog(CoreModel):
    request_modular = models.CharField(max_length=64, verbose_name='请求模块', null=True, blank=True, help_text='请求模块')
    request_path = models.CharField(max_length=400, verbose_name='请求地址', null=True, blank=True, help_text='请求地址')
    request_body = models.TextField(verbose_name='请求参数', null=True, blank=True, help_text='请求参数')
    request_method = models.CharField(max_length=8, verbose_name='请求方式', null=True, blank=True, help_text='请求方式')
    request_msg = models.TextField(verbose_name='操作说明', null=True, blank=True, help_text='操作说明')
    request_ip = models.CharField(max_length=32, verbose_name='请求ip地址', null=True, blank=True, help_text='请求ip地址')
    request_browser = models.CharField(max_length=64, verbose_name='请求浏览器', null=True, blank=True, help_text='请求浏览器')
    response_code = models.CharField(max_length=32, verbose_name='响应状态码', null=True, blank=True, help_text='响应状态码')
    request_os = models.CharField(max_length=64, verbose_name='操作系统', null=True, blank=True, help_text='操作系统')
    json_result = models.TextField(verbose_name='返回信息', null=True, blank=True, help_text='返回信息')
    status = models.BooleanField(default=False, verbose_name='响应状态', help_text='响应状态')
    request_api_name = models.CharField(max_length=255, verbose_name='接口名称')

    class Meta:
        db_table = 'system_operation_log'
        verbose_name = '操作日志'
        verbose_name_plural = verbose_name
        ordering = ('-create_time',)


class FileList(CoreModel):
    name = models.CharField(max_length=100, null=True, blank=True, verbose_name='名称', help_text='名称')
    url = models.CharField(max_length=100, null=True, blank=True, verbose_name='路径', help_text='路径')
    md5sum = models.CharField(max_length=36, blank=True, verbose_name='文件md5', help_text='文件md5')

    class Meta:
        db_table = 'system_file_list'
        verbose_name = '文件管理'
        verbose_name_plural = verbose_name
        ordering = ('-create_time',)

